using System;
using System.Data.Objects;
using System.Linq;
using Magiq.Databases;
using Magiq.Delete;
using Magiq.Insert;
using Magiq.Query;
using Magiq.Providers.Entities.Support;
using Magiq.Update;

namespace Magiq.Providers.Entities
{
    public class MagiqToEntities : MagiqToDatabases
    {
        private static LinqToEntitiesAdapter GetDatabaseAdapterFrom<T>(IQueryable<T> source)
        {
            var objectContext = source.ObjectContext();
            return objectContext == null ? null : new LinqToEntitiesAdapter(objectContext);
        }

        protected override IOrmAdapter GetDatabaseAdapterFrom<T>(IUpdate<T> update)
        {
            return GetDatabaseAdapterFrom(update.Source);
        }

        protected override IOrmAdapter GetDatabaseAdapterFromDestination<TSource, TDestination, TNew>(
            IInsert<TSource,TDestination, TNew> insert)
        {
            if (insert.Destination is ObjectQuery && !insert.Destination.IsObjectSet())
                throw new InvalidOperationException("Items cannot be added to queries.");

            return GetDatabaseAdapterFrom(insert.Destination);
        }

        protected override IOrmAdapter GetDatabaseAdapterFrom<T>(IDelete<T> delete)
        {
            return GetDatabaseAdapterFrom(delete.Source);
        }

        protected override IOrmAdapter GetDatabaseAdapterFrom<T, TChild>(QueryInfo<T, TChild> queryInfo) 
        {
            if(queryInfo.Item.IsEntityFrameworkProxy())
                return GetDatabaseAdapterFrom(queryInfo.Item);
            return null;
        }

        protected override IOrmAdapter GetDatabaseAdapterFrom<TSource, TDestination, TNew>(
            IInsert<TSource,TDestination, TNew> insert)
        {
            return insert.Source.Queryable is ObjectQuery ? GetDatabaseAdapterFromDestination(insert) : null;
        }

        protected override IOrmAdapter GetDatabaseAdapterFrom<TNew>(InsertSource<TNew> source)
        {
            return source.Queryable is ObjectQuery ? GetDatabaseAdapterFrom(source.Queryable) : null;
        }

        private static LinqToEntitiesAdapter GetDatabaseAdapterFrom(object entity)
        {
            var dataContext = entity.ObjectContext();
            return dataContext == null ? null : new LinqToEntitiesAdapter(dataContext);
        }
    }
}